package org.cglib.example;

import net.sf.cglib.core.DebuggingClassWriter;

/**
 * org.cglib.example.Teacher$$EnhancerByCGLIB$$c035fe31  extends  org.cglib.example.Teacher
 * implements net.sf.cglib.proxy.Factory
 * proxyInstance的类信息,可以看到其为被代理类的子类
 *
 * clazz类名:org.cglib.example.Teacher$$EnhancerByCGLIB$$c035fe31
 * clazz的父类名:org.cglib.example.Teacher
 * clazz的祖父类名:java.lang.Object
 * clazz类的实现接口是:net.sf.cglib.proxy.Factory
 *
 * https://www.cnblogs.com/lvbinbin2yujie/p/10284316.html
 */
public class AppCgLigProxyTest {

    /**
         注意整个过程中,我们没有手动创建原始的Teacher类的实例
         但却看到Teacher类的无参构造执行了,一定是cglib框架执行的
     */
    public static void main(String[] args) {
        //使用CGLib的代理类可以将内存中的.class文件写入本地磁盘,指定目录target/cglibGenClasses
        String classesDir = System.getProperty("user.dir") +"/cglibTest/target/cglibGenClasses4Example/";
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, classesDir);

        //第一部分,未使用代理,自己构造.产生的是原始的Teacher类
        Teacher teacher = new Teacher();
        teacher.teach("english");
        System.out.println("--------------------------------------------------------------");

        //第二部分,通过代理,产生的是增强类 org.cglib.example.Teacher$$EnhancerByCGLIB$$c035fe31
        //创建目标对象
        Teacher proxyInstance = (Teacher) new CglibProxyFactory().getProxyInstance(Teacher.class);
        System.out.println("proxyInstance的hashCode=" + System.identityHashCode(proxyInstance));

        //执行代理对象的方法,只有调用方法才触发intercept方法,从而实现对目标对象的调用
        String returnVal = proxyInstance.teach("数学");
        System.out.println("返回值returnVal=" + returnVal);
    }

    public static void printClassInfo(Class clazz) {
        System.out.println("clazz类名:" + clazz.getName());
        System.out.println("clazz的父类名:" + clazz.getSuperclass().getName());
        if (clazz.getSuperclass().getSuperclass() != null) {
            System.out.println("clazz的祖父类名:" + clazz.getSuperclass().getSuperclass().getName());
        }
        Class<?>[] interfaces = clazz.getInterfaces();
        for (Class c : interfaces
        ) {
            System.out.println("clazz类的实现接口是:" + c.getName());
        }
    }
}
